from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional

from app.core.database import get_db
from app.core.deps import get_current_user, get_tenant_id
from app.schemas.role import (
    RoleCreate, RoleUpdate, RoleResponse, RoleListResponse,
    AssignPermissionsRequest, RolePermissionResponse, RoleUserResponse
)
from app.models.user import User
from app.services.role import role_service
from app.utils.response import ResponseUtil

router = APIRouter()


@router.get("/", summary="获取角色列表", response_model=RoleListResponse)
async def get_roles(
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页数量"),
    keyword: Optional[str] = Query(None, description="搜索关键词（角色名称、编码）"),
    status: Optional[bool] = Query(None, description="角色状态"),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """分页获取角色列表"""
    try:
        # 构建查询条件
        filters = {}
        if keyword:
            filters['keyword'] = keyword
        if status is not None:
            filters['status'] = status

        # 分页查询角色
        roles, total = await role_service.get_roles_with_pagination(
            db=db,
            tenant_id=tenant_id,
            page=page,
            page_size=page_size,
            filters=filters
        )

        return RoleListResponse(
            total=total,
            items=roles
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取角色列表失败: {str(e)}"
        )


@router.post("/", summary="创建角色")
async def create_role(
    role_data: RoleCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """创建新角色"""
    try:
        # 检查角色编码是否已存在
        existing_roles = await role_service.get_role_list(db=db, tenant_id=tenant_id)
        if any(role['code'] == role_data.code for role in existing_roles):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="角色编码已存在"
            )

        # 创建角色
        role = await role_service.create_role(
            db=db,
            obj_in=role_data.model_dump(),
            tenant_id=tenant_id
        )

        return ResponseUtil.success(data=role, message="角色创建成功")
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"创建角色失败: {str(e)}"
        )


@router.get("/{role_id}", summary="获取角色详情")
async def get_role(
    role_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """根据ID获取角色详情"""
    try:
        role = await role_service.get(db, id=role_id)
        if not role or role.tenant_id != tenant_id:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )

        return ResponseUtil.success(data=role)
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取角色详情失败: {str(e)}"
        )


@router.put("/{role_id}", summary="更新角色")
async def update_role(
    role_id: int,
    role_data: RoleUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """更新角色信息"""
    try:
        # 获取角色
        role = await role_service.get(db, id=role_id)
        if not role or role.tenant_id != tenant_id:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )

        # 检查角色编码唯一性（如果更新了编码）
        if role_data.code and role_data.code != role.code:
            existing_roles = await role_service.get_role_list(db=db, tenant_id=tenant_id)
            if any(r['code'] == role_data.code for r in existing_roles):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="角色编码已存在"
                )

        # 更新角色
        updated_role = await role_service.update_role(
            db=db,
            db_obj=role,
            obj_in=role_data.model_dump(exclude_unset=True)
        )

        return ResponseUtil.success(data=updated_role, message="角色更新成功")
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"更新角色失败: {str(e)}"
        )


@router.delete("/{role_id}", summary="删除角色")
async def delete_role(
    role_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """删除角色"""
    try:
        success = await role_service.delete_role(db=db, role_id=role_id, tenant_id=tenant_id)
        if not success:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )

        return ResponseUtil.success(message="角色删除成功")
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"删除角色失败: {str(e)}"
        )


@router.get("/{role_id}/permissions", summary="获取角色权限")
async def get_role_permissions(
    role_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """获取角色的权限列表"""
    try:
        # 检查角色是否存在
        role = await role_service.get(db, id=role_id)
        if not role or role.tenant_id != tenant_id:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )

        permissions = await role_service.get_role_permissions(
            db=db, role_id=role_id, tenant_id=tenant_id
        )

        return ResponseUtil.success(data={
            "role_id": role_id,
            "role_name": role.role_name,
            "permissions": permissions
        })
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取角色权限失败: {str(e)}"
        )


@router.put("/{role_id}/permissions", summary="分配角色权限")
async def assign_role_permissions(
    role_id: int,
    permission_data: AssignPermissionsRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """分配权限给角色"""
    try:
        # 检查角色是否存在
        role = await role_service.get(db, id=role_id)
        if not role or role.tenant_id != tenant_id:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )

        # 分配权限
        await role_service.assign_permissions(
            db=db,
            role_id=role_id,
            permission_ids=permission_data.permission_ids,
            tenant_id=tenant_id
        )

        return ResponseUtil.success(message="权限分配成功")
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"分配权限失败: {str(e)}"
        )


@router.get("/{role_id}/users", summary="获取角色用户")
async def get_role_users(
    role_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
    tenant_id: str = Depends(get_tenant_id)
):
    """获取拥有此角色的用户列表"""
    try:
        # 检查角色是否存在
        role = await role_service.get(db, id=role_id)
        if not role or role.tenant_id != tenant_id:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )

        users = await role_service.get_role_users(
            db=db, role_id=role_id, tenant_id=tenant_id
        )

        return ResponseUtil.success(data={
            "role_id": role_id,
            "role_name": role.role_name,
            "users": users
        })
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取角色用户失败: {str(e)}"
        )